package org.codehaus.activemq.web;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.codehaus.activemq.message.ActiveMQQueue;
import org.codehaus.activemq.message.ActiveMQTopic;

public abstract class MessageServletSupport extends HttpServlet
{
  private boolean defaultTopicFlag = true;
  private Destination defaultDestination;
  private String destinationParameter = "destination";
  private String topicParameter = "topic";
  private String bodyParameter = "body";

  public void init(ServletConfig servletConfig) throws ServletException
  {
    super.init(servletConfig);

    String name = servletConfig.getInitParameter("topic");
    if (name != null) {
      this.defaultTopicFlag = asBoolean(name);
    }

    log("Defaulting to use topics: " + this.defaultTopicFlag);

    name = servletConfig.getInitParameter("destination");
    if (name != null) {
      if (this.defaultTopicFlag) {
        this.defaultDestination = new ActiveMQTopic(name);
      }
      else {
        this.defaultDestination = new ActiveMQQueue(name);
      }

    }

    WebClient.initConnectionFactory(getServletContext());
  }

  protected WebClient createWebClient(HttpServletRequest request) {
    return new WebClient(getServletContext());
  }

  public static boolean asBoolean(String param) {
    return (param != null) && (param.equalsIgnoreCase("true"));
  }

  protected WebClient getWebClient(HttpServletRequest request)
  {
    HttpSession session = request.getSession(true);
    WebClient client = WebClient.getWebClient(session);
    if (client == null) {
      client = createWebClient(request);
      session.setAttribute("org.codehaus.activemq.webclient", client);
    }
    return client;
  }

  protected void appendParametersToMessage(HttpServletRequest request, TextMessage message) throws JMSException
  {
    for (Iterator iter = request.getParameterMap().entrySet().iterator(); iter.hasNext(); ) {
      Map.Entry entry = (Map.Entry)iter.next();
      String name = (String)entry.getKey();
      if ((!this.destinationParameter.equals(name)) && (!this.topicParameter.equals(name)) && (!this.bodyParameter.equals(name))) {
        Object value = entry.getValue();
        if ((value instanceof Object[])) {
          Object[] array = (Object[])value;
          if (array.length == 1) {
            value = array[0];
          }
          else {
            log("Can't use property: " + name + " which is of type: " + value.getClass().getName() + " value");
            value = null;
            int i = 0; for (int size = array.length; i < size; i++) {
              log("value[" + i + "] = " + array[i]);
            }
          }
        }
        if (value != null)
          message.setObjectProperty(name, value);
      }
    }
  }

  protected Destination getDestination(WebClient client, HttpServletRequest request)
    throws JMSException, NoDestinationSuppliedException
  {
    String destinationName = request.getParameter(this.destinationParameter);
    if (destinationName == null) {
      if (this.defaultDestination == null) {
        return getDestinationFromURI(client, request);
      }

      return this.defaultDestination;
    }

    return getDestination(client, request, destinationName);
  }

  protected Destination getDestinationFromURI(WebClient client, HttpServletRequest request)
    throws NoDestinationSuppliedException, JMSException
  {
    String uri = request.getPathInfo();
    if (uri == null) {
      throw new NoDestinationSuppliedException();
    }

    if (uri.startsWith("/")) {
      uri = uri.substring(1);
    }
    uri = uri.replace('/', '.');
    return getDestination(client, request, uri);
  }

  protected Destination getDestination(WebClient client, HttpServletRequest request, String destinationName)
    throws JMSException
  {
    if (isTopic(request)) {
      return client.getSession().createTopic(destinationName);
    }

    return client.getSession().createQueue(destinationName);
  }

  protected boolean isTopic(HttpServletRequest request)
  {
    boolean aTopic = this.defaultTopicFlag;
    String aTopicText = request.getParameter(this.topicParameter);
    if (aTopicText != null) {
      aTopic = asBoolean(aTopicText);
    }
    return aTopic;
  }

  protected long asLong(String name) {
    return Long.parseLong(name);
  }

  protected String getPostedMessageBody(HttpServletRequest request)
    throws IOException
  {
    String answer = request.getParameter(this.bodyParameter);
    if (answer == null)
    {
      BufferedReader reader = request.getReader();
      StringBuffer buffer = new StringBuffer();
      while (true) {
        String line = reader.readLine();
        if (line == null) {
          break;
        }
        buffer.append(line);
        buffer.append("\n");
      }
      return buffer.toString();
    }
    return answer;
  }
}